#include "uart.h"

/***************************
 *name  : open_port
 *功能  : 打开串口
 *参数  : com_port 指定端口
 *返回值: 成功返回文件描述符，失败返回负值
 *wuquanwei 2011.4.28最后修改
 * *************************/
/***************************************
 *name    : open_port
 *功能描述: 打开串口
 *入口参数: 串口号
 *返 回 值: 成功返回文件描述符，失败返回负值
 *作    者:吴权威
 *最后修改时间:2011.4.28
 ***************************************/
int open_port(int com_port)
{
    int fd;
    char *dev[]={"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5"};

    if((com_port < 0) || (com_port > 4) ){
        printf("the port is out range");
        return -1;
    }
    /*open port*/
    fd = open(dev[com_port - 1], O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd < 0){
        fd = open(dev[com_port - 1], O_RDWR | O_NOCTTY | O_NDELAY);
        if(fd < 0){ 
            perror("open serial port");
            return -1;
        }
    }
    
    if(fcntl(fd, F_SETFL,0) < 0){
        perror("fcntl F_SETFL");
    }

    if(isatty(fd) == 0){
        perror("isatty is not a terminal device");
    }
    return fd;
}

/******************************
 *name    : set_port
 *功能描述: 设置串口参数
 *入口参数: fd 文件描述符, baud_rate 波特率, data_bits 数据位, 
 *          parity 奇偶校验, stop_bits 停止位
 *返 回 值: 成功返回0，失败返回-1
 *作    者: 吴权威
 *最后修改: 2011.4.28
 ******************************/
int set_port(int fd, int baud_rate, 
             int data_bits, char parity, int stop_bits)
{
    struct termios new_cfg, old_cfg;
    int speed_arry[]= {B2400, B4800, B9600, B19200, B38400, B115200};
    int speed[]={2400,4800,9600,19200,38400,115200};
    int i = 0; 
    
    /*save and test the serial port*/
    if(tcgetattr(fd, &old_cfg) < 0){
        perror("tcgetattr");
        return -1;
    }

    new_cfg = old_cfg;
    cfmakeraw(&new_cfg);    //配置为原来配置
    new_cfg.c_cflag &= ~ CSIZE;     //用数据位掩码清空数据位的设置
    
    /*set baud_rate*/
    for(i = sizeof(speed_arry) / sizeof(speed_arry[0]); i > 0; i--)
    {
        if(baud_rate == speed[i]){
            cfsetispeed(&new_cfg,speed_arry[i]);
            cfsetospeed(&new_cfg,speed_arry[i]);
        }
    }


    switch(data_bits)   /*设置数据位*/
    {
        case 7:
                new_cfg.c_cflag |= CS7;
                break;
                
        default:
        case 8:
                new_cfg.c_cflag |= CS8;
                break;
    }
    
    switch(parity)
    {
        default:
        case 'N':
        case 'n':
        {
            new_cfg.c_cflag &= ~PARENB;     //清除校验位
            new_cfg.c_iflag &= ~INPCK;      //关闭奇偶校验
        }
        break;

        case 'o':
        case 'O':
        {
            new_cfg.c_cflag |= (PARODD | PARENB); //使用奇校验不是用偶校验
            new_cfg.c_iflag |= INPCK;     
        }
        break;

        case 'e':
        case 'E':
        {
            new_cfg.c_cflag |= PARENB;
            new_cfg.c_cflag &= ~PARODD;     //使用偶校验
            new_cfg.c_iflag |= INPCK;
        }
        break;

        case 's':
        case 'S':
        {
            new_cfg.c_cflag &= ~PARENB;
            new_cfg.c_cflag &= ~CSTOPB;
        }
        break;
    }

    switch(stop_bits)
    {
        default:
        case 1:
        {
            new_cfg.c_cflag &= ~CSTOPB;
        }
        break;

        case 2:
        {
            new_cfg.c_cflag |= CSTOPB;
        }
        break;
    }

    /*set wait time*/
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN]  = 1;

    tcflush(fd, TCIFLUSH);  //处理未接收字符
    if((tcsetattr(fd, TCSANOW, &new_cfg)) < 0)
    {
        perror("tcsetattr");
        return -1;
    }
    return 0;
}
